package com.gjy.spring.boot3;

import org.springframework.boot.DefaultBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;

import java.lang.reflect.Constructor;
import java.util.List;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-12-18 10:05:03
 */
@SpringBootApplication
public class Boot2App {

    public static void main(String[] args) throws Exception {

        // 添加 app 监听器
        SpringApplication spring = new SpringApplication(Boot2App.class);
        spring.addListeners(e -> System.out.println(e.getClass()));

        // 获取事件发布器实现类名, [获取 spring.factories 接口的实现]
        List<String> list = SpringFactoriesLoader.loadFactoryNames(SpringApplicationRunListener.class, Boot2App.class.getClassLoader());
        for (String s : list) {
            System.out.println("s = " + s);
            // 创建事件发布器的实例
            Class<?> cls = Class.forName(s);
            Constructor<?> constructor = cls.getConstructor(SpringApplication.class, String[].class);
            SpringApplicationRunListener publisher = (SpringApplicationRunListener) constructor.newInstance(spring, args);
            // 发布事件
            DefaultBootstrapContext defaultBootstrapContext = new DefaultBootstrapContext();
            publisher.starting(defaultBootstrapContext); // SpringBoot 开始启动
            publisher.environmentPrepared(defaultBootstrapContext, new StandardEnvironment()); // 环境信息准备完成
            GenericApplicationContext context = new GenericApplicationContext();
            publisher.contextPrepared(context); // 在spring容器创建，并调用初始化器之后，发送此事件，还要补充一些BeanDefinition[XML,配置类,组件扫描]
            publisher.contextLoaded(context); //BeanDefinition加载完后，发送此事件
            context.refresh();
            publisher.started(context); // Spring容器初始化完成，refresh 方法调用完毕
            publisher.running(context); // SpringBoot 启动完成
            publisher.failed(context, new Exception("启动失败")); // SpringBoot 启动失败
        }

    }
}
